package com.vt.common.security.util.parser;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.vt.admin.api.dto.user.VueUserInfo;
import com.vt.common.core.annotation.UName;
import com.vt.common.core.constant.CommonConstant;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @Auther: panZha
 * @Date: 2018/11/9 14:12
 * @Description:
 */
@Component
@AllArgsConstructor
public class UNameParser extends ResultDataParser {

    StringRedisTemplate redisTemplate;

    public void parse(Object data) {
        Collection cos = getResData(data);

        if (null == cos)
            return;
        Map<String, VueUserInfo> userMap = getUserMaps();
        for (Object obj : cos) {
            parseObj(obj, userMap);
        }
    }

    private void parseObj(Object obj, Map<String, VueUserInfo> userMap) {
        Field[] fs = ReflectUtil.getFields(obj.getClass());

        Field id;
        String idV;
        Object v;
        for (Field f : fs) {
            id = getIdField(f, fs);
            if (null == id)
                continue;

            v = ReflectUtil.getFieldValue(obj, id);
            if (null == v)
                continue;

            idV = v.toString();

            ReflectUtil.setFieldValue(obj, f,
                    userMap.containsKey(idV) ? userMap.get(idV).getName() : null);
        }
    }

    protected Field getIdField(Field f, Field[] fs) {
        UName annotation = f.getAnnotation(UName.class);
        if (null == annotation)
            return null;

        List<String> ss = new ArrayList(2);
        if (StrUtil.isNotEmpty(annotation.value())) {
            ss.add(annotation.value());
        } else {
            String s = StrUtil.removeSuffix(f.getName(), "Name");
            ss.add(StrUtil.join(s, "Id"));
            ss.add(s);
        }

        for (Field field : fs) {
            if (ss.contains(field.getName()))
                return field;
        }
        return null;
    }

    private List<VueUserInfo> getUsers() {
        return JSONUtil.toList(JSONUtil.parseArray(
                redisTemplate.opsForValue().get(CommonConstant.REDIS_USER_PREFIX))
                , VueUserInfo.class);
    }

    private Map<String, VueUserInfo> getUserMaps() {
        List<VueUserInfo> list = getUsers();
        Map<String, VueUserInfo> map = new HashMap(list.size());
        for (VueUserInfo u : list) {
            map.put(u.getUserId(), u);
        }
        return map;
    }
}
